﻿using System;
using System.Security;
using System.Windows.Forms;
using SQLDiagConfiguration.Properties;

namespace SQLDiagConfiguration
{
    /// <summary>
    /// Enumeration detailing the various Panes present in the Options Pane
    /// </summary>
    enum lvPageTags
    {
        empty = 0,
        welcome = 1,
        authentication = 2,
        machine = 3,
        instance = 4,
        profiler = 5,
        perfmon = 6,
        producers = 7,
        analyzers = 8
    }
    
    /// <summary>
    /// This is the main form for the application
    /// </summary>
    public partial class SQLDiagConfigurationOptions : Form
    {
        #region Properties
        /// <summary>
        /// This object holds all of the state information for use by this form
        /// and all option pages
        /// </summary>
        private DiagInfoObject sqlDiagInfo;

        public DiagInfoObject SqlDiagInfo
        {
            get { return sqlDiagInfo; }
            set { sqlDiagInfo = value; }
        }

        #endregion Properties

        #region Constructor
        public SQLDiagConfigurationOptions()
        {
            InitializeComponent();
            SqlDiagInfo = new DiagInfoObject(this);
            bool showOpenFileDialog = false;
            LoadPages();
            LoadConfigFile(showOpenFileDialog);
            SetTextValues();
        }
        #endregion Constructor

        #region Event Handlers
        /// <summary>
        /// This event handler is responsible for hiding/showing pages in the panelOptions panel
        /// in response to users selected an item in the lvOptions listview control
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lvOptionPages_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            foreach (Control c in panelOptions.Controls)
            {
                c.Visible = false;
            }
            // Now find out which option was selected in the lvOptions listview and make the appropriate
            // page visible in the panelOptions panel
            lvPageTags tab = (lvPageTags)e.Item.Tag;
            
            switch (tab)
            {
                case lvPageTags.welcome:
                    panelOptions.Controls[0].Visible = true;
                    break;
                case lvPageTags.authentication:
                    panelOptions.Controls[1].Visible = true;
                    break;
                case lvPageTags.machine:
                    panelOptions.Controls[2].Visible = true;
                    break;
                case lvPageTags.instance:
                    panelOptions.Controls[3].Visible = true;
                    break;
                case lvPageTags.profiler:
                    panelOptions.Controls[4].Visible = true;
                    break;
                case lvPageTags.perfmon:
                    panelOptions.Controls[5].Visible = true;
                    break;
                case lvPageTags.producers:
                    panelOptions.Controls[6].Visible = true;
                    break;
                case lvPageTags.analyzers:
                    panelOptions.Controls[7].Visible = true;
                    break;
            }
        }
        /// <summary>
        /// User has chosen to end the application
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        /// <summary>
        /// The user has chosen to save their work to either the same file or a new one of their chossing
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSave_Click(object sender, EventArgs e)
        {
            // Root the SaveFileDialog in the same directory that they started in, and with the same file name
            saveFileDialog1.InitialDirectory = SqlDiagInfo.ConfigPath;
            saveFileDialog1.FileName = SqlDiagInfo.ConfigFile;
            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                // Capture that path for the actual saving of the xml file
                SqlDiagInfo.ConfigPath = saveFileDialog1.InitialDirectory;
                SqlDiagInfo.ConfigFile = saveFileDialog1.FileName;

                // Tell each page to update it's part of the configuration file
                foreach (Control c in panelOptions.Controls)
                {
                    ((BasePage)c).SaveState();
                }

                // Persist changes to our file
                try
                {
                    SqlDiagInfo.SQLDiagConfigDataSet.WriteXml(SqlDiagInfo.ConfigFile);
                    // Now reselect the Welcome Page so they can start over if they wish
                    lvOptionPages.Items[1].Selected = true;
                    lvOptionPages.Select();
                    lblFileName.Text = Resources.strEmptyString;
                    lblSQLVersion.Text = Resources.strEmptyString;

                    ShowListViewPages(false);
                    // Only allow saving if a file has been loaded
                    btnSave.Enabled = false;
                    MessageBox.Show(Resources.strFileSaved, Resources.strFileSaveTitle, MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                catch (SecurityException se)
                {
                    MessageBox.Show(se.Message, Resources.strCantSaveFile, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

            }
        }
        /// <summary>
        /// This user has asked to open a SQLDiag configuration file for editing
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOpen_Click(object sender, EventArgs e)
        {
            bool showOpenFileDialog = true;
            LoadConfigFile(showOpenFileDialog);
        }
        #endregion Event Handlers

        #region Helper Methods
        public void LoadConfigFile(bool showOpenFileDialog)
        {
            // Directory and FileName
            // Right now it defaults to values set in SQLDiagInfoObject
            // configPath = @"C:\Program Files\Microsoft SQL Server\100\Tools\Binn"
            // configFile = @"SQLDiag.xml"
            if (showOpenFileDialog)
            {
                openFileDialog1.InitialDirectory = SqlDiagInfo.ConfigPath;
                openFileDialog1.FileName = SqlDiagInfo.ConfigFile;
                if (openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    // Save the directory and filename selected by the user for later
                    string fileName = openFileDialog1.FileName;
                    int index = fileName.LastIndexOf(Resources.strBackSlash, StringComparison.CurrentCulture);
                    if (index > 0)
                    {
                        SqlDiagInfo.ConfigPath = fileName.Substring(0, index);
                        SqlDiagInfo.ConfigFile = openFileDialog1.SafeFileName;
                    }
                }
            }
            // They have choosen a file to edit

            // Since they user may be editing multiple files in one session
            // we have to disassociated the DataSet from the XmlDataDocument
            // in order to reuse these objects
            SqlDiagInfo.Reset();
            ShowListViewPages(false);
            // Use the DataSet ReadXml method to load the file and automatically
            // create DataTables for each item in the file
            SqlDiagInfo.SQLDiagConfigDataSet.ReadXml(SqlDiagInfo.FullConfigPath);

            if (SqlDiagInfo.IsValid == true)
            {
                // And let the user know what version this file targets
                string sqlVersion = Resources.strSQLVersion;
                SqlDiagInfo.Version = SqlDiagInfo.SQLDiagConfigDataSet.Tables[Resources.strInstance].Rows[0][Resources.strSSVer].ToString();
                sqlVersion += GetVersionString(SqlDiagInfo.Version);

                sqlVersion += Resources.strVersionText;
                lblSQLVersion.Text = sqlVersion;

                foreach (Control c in panelOptions.Controls)
                {
                    // Each page knows how to load it's own state
                    ((BasePage)c).LoadState();
                }
                // Now we can show all the other pages in the list view
                ShowListViewPages(true);

                // We have loaded a file, so hide the Welcome Page and Show the Authentication page.
                // if we have displayed the OpenFileDialog otherwise don't do anything
                if (!showOpenFileDialog)
                {
                    panelOptions.Controls[0].Visible = true;
                }
                else
                {
                    panelOptions.Controls[0].Visible = false;
                    panelOptions.Controls[1].Visible = true;
                }
                // Automatically move the Page selection to the Authentication Page once 
                // a file has been loaded
                lvOptionPages.Items[1].Selected = true;
                lvOptionPages.Select();

                // Update the status bar to let the user know which file is being edited
                lblFileName.Text = SqlDiagInfo.FullConfigPath;

                // Now that a file has been loaded, enable the save button
                btnSave.Enabled = true;
            }
            else
            {
                // Notify the user that we cannot process this file...
                MessageBox.Show(SqlDiagInfo.InvalidFileType, Resources.strInvalidMessageBoxTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
                // Remove all references to the file since it is not in the correct format.
                SqlDiagInfo.Reset();
            }
        }
        /// <summary>
        /// This method creates all the pages, loades them into the panelOptions control collection
        /// and displays the Welcome Page
        /// </summary>
        private void LoadPages()
        {
            WelcomePage wp = new WelcomePage(SqlDiagInfo);
            wp.Visible = true;
            AuthenticationMethodPage cip = new AuthenticationMethodPage(SqlDiagInfo);
            cip.Visible = false;
            MachineInfoPage mip = new MachineInfoPage(SqlDiagInfo);
            mip.Visible = false;
            InstanceInfoPage iip = new InstanceInfoPage(SqlDiagInfo);
            iip.Visible = false;
            ProfilerOptionsPage stp = new ProfilerOptionsPage(SqlDiagInfo);
            stp.Visible = false;
            PerfmonOptionsPage pp = new PerfmonOptionsPage(SqlDiagInfo);
            pp.Visible = false;
            ProducersPage prop = new ProducersPage(SqlDiagInfo);
            prop.Visible = false;
            AnalyzersPage ap = new AnalyzersPage(SqlDiagInfo);
            ap.Visible = false;

            panelOptions.Controls.Add(wp);
            panelOptions.Controls.Add(cip);
            panelOptions.Controls.Add(mip);
            panelOptions.Controls.Add(iip);
            panelOptions.Controls.Add(stp);
            panelOptions.Controls.Add(pp);
            panelOptions.Controls.Add(prop);
            panelOptions.Controls.Add(ap);
            // Make sure the Welcome Page is selected
            ShowListViewPages(false);
            ListViewItem lvi = lvOptionPages.Items.Add(Resources.strPanelWelcome, 0);
            lvi.Selected = true;
            lvi.Tag = 1;
            lvOptionPages.Select();

        }
        /// <summary>
        /// This method is used to add or remove items in the lvOptions list view.
        /// We will only show the Welcome page until the user has opened a file for editing
        /// When the user saves, we again remove all pages except for the Welcome page.
        /// </summary>
        /// <param name="show"></param>
        public void ShowListViewPages(bool show)
        {
            // We only want these pages to show after the user has selected a file to configure.
            if (show == true)
            {
                //ListViewItem lvi = lvOptionPages.Items.Add(Resources.strPanelWelcome, 0);
                //lvi.Tag = 1; 
                //lvi.Selected = true;
                ListViewItem lvi = lvOptionPages.Items.Add(Resources.strPanelAuthentication, 0);
                lvi.Tag = 2;
                lvi = lvOptionPages.Items.Add(Resources.strPanelMachine, 0);
                lvi.Tag = 3;
                lvi = lvOptionPages.Items.Add(Resources.strPanelInstance, 0);
                lvi.Tag = 4;
                lvi = lvOptionPages.Items.Add(Resources.strPanelProfiler, 0);
                lvi.Tag = 5;
                lvi = lvOptionPages.Items.Add(Resources.strPanelPerfmon, 0);
                lvi.Tag = 6;
                lvi = lvOptionPages.Items.Add(Resources.strPanelProducers, 0);
                lvi.Tag = 7;
                lvi = lvOptionPages.Items.Add(Resources.strPanelAnalyzers, 0);
                lvi.Tag = 8;
            }
            else
            {
                // Remove the pages we don't want the user interacting with until after a file has been loaded
                for (int lvi = lvOptionPages.Items.Count - 1; lvi >= 2; lvi--)
                {
                    lvOptionPages.Items[lvi].Remove();
                }
            }
            lvOptionPages.Select();
        }
        public static string GetVersionString(string version)
        {
            string sqlVersion = "";
            if (version == Resources.strVer9)
            {
                sqlVersion += Resources.str2005;
            }
            if (version == Resources.strVer10)
            {
                sqlVersion += Resources.str2008;
            }
            if (version == Resources.strVer1050)
            {
                sqlVersion += Resources.str2008R2;
            }
            if (version == Resources.strVer11)
            {
                sqlVersion += Resources.strSQL11;
            }
            return sqlVersion;
        }
        public void SetTextValues()
        {
            btnCancel.Text = Resources.strButtonClose;
            btnOpen.Text = Resources.strButtonOpen;
            btnSave.Text = Resources.strButtonSave;
            txtMessage.Text = Resources.strSelectAPage;
            this.Text = Resources.strFormTitle;
        }
        #endregion Helper Methods
    } 
}
